package com.gitee.deament.server.core.cli.db.list;

import com.gitee.deament.core.exception.DataException;
import com.gitee.deament.server.config.SystemConfig;
import com.gitee.deament.server.core.annotation.CliHander;
import com.gitee.deament.server.core.cli.AbstractCli;
import com.gitee.deament.server.core.data.ConnectData;
import com.gitee.deament.server.core.data.DBData;
import com.gitee.deament.server.core.data.datatype.Value;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;

import java.util.LinkedList;
import java.util.List;

/**
 * LPUSH key value [value …]
 * 可用版本： >= 1.0.0
 * 时间复杂度： O(1)
 * 将一个或多个值 value 插入到列表 key 的表头
 *
 * 如果有多个 value 值，那么各个 value 值按从左到右的顺序依次插入到表头： 比如说，对空列表 mylist 执行命令 LPUSH mylist a b c ，列表的值将是 c b a ，这等同于原子性地执行 LPUSH mylist a 、 LPUSH mylist b 和 LPUSH mylist c 三个命令。
 *
 * 如果 key 不存在，一个空列表会被创建并执行 LPUSH 操作。
 *
 * 当 key 存在但不是列表类型时，返回一个错误。
 * @author deament
 */
@CliHander(command = "LPUSH")
public class LPUSHcli extends AbstractCli {
    @Override
    public void executeCli(ChannelHandlerContext channelHandlerContext, String command) {
        List<String> cliValues = getValues(command);
        if (cliValues.size() <3) {
            channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame("ERR wrong number of arguments for 'LPUSH' command"));
            return;
        }
        int db = ConnectData.SELECT_DB_STORAGE.getUseDB(channelHandlerContext.channel().id().asLongText());
        DBData dbData = SystemConfig.dbData;
        String key = cliValues.get(1);
        LinkedList<String> listValues= new LinkedList<>();
        for(int i=2;i<cliValues.size();i++){
            listValues.add(0,cliValues.get(i));
        }

        Value<List<String>> value = new Value<>();
        value.getValue().addAll(0,listValues);
        Value dbValue =dbData.getList(db, key);
        if (dbValue != null) {
            if (!(dbValue.getValue() instanceof List)) {
                throw new DataException("WRONGTYPE Operation against a key holding the wrong kind of value");
            }
            ((List) dbValue.getValue()).addAll(0,listValues);
            channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame(dbData.getListDataLength(db, key)+""));
            return ;
        }
        dbData.setListData(db, key, value);
        channelHandlerContext.channel().writeAndFlush(value.getValue().size()+"");
    }
}
